package com.netx.data;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

import com.netx.generics.basic.IntegrityException;


public class MySQLDriver implements DatabaseDriver {

	public MySQLDriver() {
		super();
	}
	
	public String getJdbcDriverName() {
		return "com.mysql.jdbc.Driver";
	}
	
	public String getNativeBoolean() {
		return "TINYINT";
	}

	public String getNativeByte() {
		return "TINYINT UNSIGNED";
	}

	public String getNativeShort() {
		return "SMALLINT";
	}

	public String getNativeInt() {
		return "INT";
	}

	public String getNativeLong() {
		return "BIGINT";
	}

	public String getNativeFloat() {
		return "FLOAT";
	}

	public String getNativeDouble() {
		return "DOUBLE";
	}

	public String getNativeText(int length) {
		if(length < Math.pow(2, 8)) { // 256
			return "VARCHAR("+length+")";
		}
		else if(length < Math.pow(2, 16)) { // 65536, 64K
			return "TEXT";
		}
		else if(length < Math.pow(2, 24)) { // 16777216, 16M
			return "MEDIUMTEXT";
		}
		else if(length < Math.pow(2, 32)) { // 4294967296, 4G
			return "LONGTEXT";
		}
		else {
			throw new IllegalArgumentException("invalid field length: "+length);
		}
	}

	public String getNativeBinary(int length) {
		if(length < Math.pow(2, 8)) { // 256
			return "VARCHAR("+length+") BINARY";
		}
		else if(length < Math.pow(2, 16)) { // 65536, 64K
			return "BLOB";
		}
		else if(length < Math.pow(2, 24)) { // 16777216, 16M
			return "MEDIUMBLOB";
		}
		else if(length < Math.pow(2, 32)) { // 4294967296, 4G
			return "LONGBLOB";
		}
		else {
			throw new IllegalArgumentException("invalid field length: "+length);
		}
	}

	public String getNativeDate() {
		return "DATE";
	}

	public String getNativeTime() {
		return "TIME";
	}

	public DateFormat getDateTimeFormat() {
		return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	}

	public DateFormat getDateFormat() {
		return new SimpleDateFormat("yyyy-MM-dd");
	}
	public DateFormat getTimeFormat() {
		return new SimpleDateFormat("HH:mm:ss");
	}

	public boolean isMalformedQueryException(SQLException sqle) {
		// Format 1: <put here>
		if(sqle.getMessage().indexOf("syntax") != -1) {
			return true;
		}
		// Format 2: <put here>
		else if(sqle.getMessage().indexOf("Table") != -1 && sqle.getMessage().indexOf("doesn't exist") != -1) {
			return true;
		}
		// Format 3: java.sql.SQLException: Column not found, message from server: "Unknown column 'codigo' in 'order clause'" ou "Unknown column 'registration_date' in 'field list'"
		else if(sqle.getMessage().indexOf("Unknown column") != -1) {
			return true;
		}
		else {
			return false;
		}
	}

	public boolean isDatabaseFailureException(SQLException sqle) {
		// Format 1: Server connection failure during transaction.\nAttempted reconnect 3 times. Giving up.
		if(sqle.getMessage().startsWith("Server connection failure during transaction.")) {
			return true;
		}
		else {
			return false;
		}
	}

	public boolean isConstraintException(SQLException sqle) {
		if(sqle.getMessage().indexOf("Duplicate entry") != -1) {
			return true;
		}
		else {
			return false;
		}
	}

	public void initConstraintException(ConstraintException ce, Field[] sentFields, Object[] sentValues) {
		// message format, while trying to insert a double unique index field:
		// Invalid argument value,  message from server: "Duplicate entry 'carlos-passwd' for key 2"
		String[] array = ce.getMessage().split("[']");
		array = array[1].split("[-]");
		// for this case, set as violating field the first one (with value "carlos"):
		String fieldValue = array[0];
		for(int i=0; i<sentValues.length; i++) {
			if(fieldValue.equals(sentValues[i].toString())) {
				ce.setViolationSource(sentFields[i], sentValues[i]);
				return;
			}
		}
		// field should be detected:
		throw new IntegrityException();
	}

}
